local zip = {}

---@class chicken_coop
---@field level integer 等级
---@field next integer[] 数组长度代表鸡的数量，每个数字代表鸡下次下蛋时间，每个数字最大为60
---@field nest integer[] 数组长度代表鸡窝数量，每个数字代表鸡窝中鸡蛋的数量，每个鸡窝最多3个鸡蛋，如果所有鸡窝都满了则所有next停止倒计时。


---@class dumplings
---@field 猪圈 pigstyMeta 猪圈产业
---@field 鸡圈 chicken_coop 鸡圈产业
---@field 麦田 farmMeta 麦田产业
---@field 加工台 workbenchMeta 加工台产业
---@field 门店 storeMeta 门店产业
---@field 锅炉 craftingMeta 锅炉产业

local base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

-- 定义数据结构 schema
local SCHEMA = {
    ["猪圈"] = {
        { name = "level",  type = "int" },
        { name = "next",   type = "int" },
        { name = "retain", type = "int" }
    },
    ["鸡圈"] = {
        { name = "level", type = "int" },
        { name = "next",  type = "int_array" },
        { name = "nest",  type = "int_array" }
    },
    ["麦田"] = {
        { name = "芦苇", type = "int_array" },
        { name = "水稻", type = "int_array" },
        { name = "甘蔗", type = "int_array" },
        { name = "枣树", type = "int_array" }
    },
    ["加工台"] = {
        { name = "level", type = "int" },
        { name = "1",     type = "int_pair" },
        { name = "2",     type = "int_pair" },
        { name = "3",     type = "int_pair" },
        { name = "4",     type = "int_pair" },
        { name = "5",     type = "int_pair" },
        { name = "6",     type = "int_pair" },
        { name = "7",     type = "int_pair" },
        { name = "8",     type = "int_pair" }
    },
    ["门店"] = {
        { name = "level",  type = "int" },
        { name = "credit", type = "int" },
        { name = "assets", type = "int" },
        { name = "bonus",  type = "int_array" }
    },
    ["锅炉"] = {
        { name = "level",  type = "int" },
        { name = "next", type = "int" },
        { name = "product", type = "int" },
        { name = "crafting_status", type = "int" },
        { name = "materials",  type = "int_array" }
    }
}

-- 更健壮的Base64编码
local function base64_encode(data)
    local result = {}
    local len = #data

    for i = 1, len, 3 do
        local b1, b2, b3 = data:byte(i, i + 2)
        local n = (b1 or 0) * 65536 + (b2 or 0) * 256 + (b3 or 0)

        local chars = {
            base64_chars:sub(math.floor(n / 262144) % 64 + 1, math.floor(n / 262144) % 64 + 1),
            base64_chars:sub(math.floor(n / 4096) % 64 + 1, math.floor(n / 4096) % 64 + 1),
            (b2 and base64_chars:sub(math.floor(n / 64) % 64 + 1, math.floor(n / 64) % 64 + 1)) or "=",
            (b3 and base64_chars:sub(n % 64 + 1, n % 64 + 1)) or "="
        }

        table.insert(result, table.concat(chars))
    end

    return table.concat(result)
end

-- 完全重写的Base64解码函数
local function base64_decode(str)
    local result = {}
    local len = #str
    local i = 1

    while i <= len do
        local c1, c2, c3, c4 = str:byte(i, i + 3)
        i = i + 4

        if not c1 then break end

        local pos1 = c1 and (base64_chars:find(string.char(c1), 1, true) or 0)
        local pos2 = c2 and (base64_chars:find(string.char(c2), 1, true) or 0)
        local pos3 = c3 and (c3 == 61 and 0 or base64_chars:find(string.char(c3), 1, true) or 0)
        local pos4 = c4 and (c4 == 61 and 0 or base64_chars:find(string.char(c4), 1, true) or 0)

        -- 转换为0-based索引
        pos1 = pos1 > 0 and (pos1 - 1) or 0
        pos2 = pos2 > 0 and (pos2 - 1) or 0
        pos3 = pos3 > 0 and (pos3 - 1) or 0
        pos4 = pos4 > 0 and (pos4 - 1) or 0

        local n = pos1 * 262144 + pos2 * 4096 + pos3 * 64 + pos4

        if c4 ~= 61 and c3 ~= 61 then -- 3个字节
            table.insert(result, string.char(
                math.floor(n / 65536) % 256,
                math.floor(n / 256) % 256,
                n % 256
            ))
        elseif c4 == 61 and c3 ~= 61 then -- 2个字节
            table.insert(result, string.char(
                math.floor(n / 65536) % 256,
                math.floor(n / 256) % 256
            ))
        elseif c3 == 61 then -- 1个字节
            table.insert(result, string.char(
                math.floor(n / 65536) % 256
            ))
        end
    end

    return table.concat(result)
end

-- 整数编码函数（支持大数值）
local function encode_number(value)
    if value < 0 then
        value = 0 -- 防止负数
    end

    local bytes = {}
    repeat
        local byte = value % 128
        value = math.tointeger(math.floor(value / 128))
        if value > 0 then
            byte = byte + 128 -- 设置继续标志
        end
        table.insert(bytes, 1, string.char(byte))
    until value == 0
    return table.concat(bytes)
end

-- 整数解码函数（安全无死循环）
local function decode_number(data, index)
    local value = 0
    local shift = 0
    local byte

    for _ = 1, 10 do -- 最多处理10字节（支持2^70）
        if index > #data then
            return value, index
        end

        byte = data:byte(index)
        index = index + 1

        value = value + ((byte % 128) * (2 ^ shift))
        shift = shift + 7

        if byte < 128 then
            return value, index
        end
    end

    return value, index -- 防止无限循环
end

-- 序列化函数（表 → ASCII字符串）
function zip.serialize(data)
    local bytes = {}

    -- 辅助函数：添加变长编码数值
    local function add_value(v)
        table.insert(bytes, encode_number(v))
    end

    -- 辅助函数：添加数组
    local function add_array(arr)
        add_value(#arr)
        for _, v in ipairs(arr) do
            add_value(v)
        end
    end

    -- 辅助函数：添加键值对
    local function add_pair(pair)
        add_value(pair[1])
        add_value(pair[2])
    end

    -- 根据schema序列化数据
    for section, fields in pairs(SCHEMA) do
        local section_data = data[section]
        if not section_data then
            -- 缺少整个部分，跳过
            goto continue
        end

        for _, field in ipairs(fields) do
            local value = section_data[field.name]

            if field.type == "int" then
                add_value(value or 0)
            elseif field.type == "int_array" then
                add_array(value or {})
            elseif field.type == "int_pair" then
                add_pair(value or { 0, 0 })
            end
        end

        ::continue::
    end

    return base64_encode(table.concat(bytes))
end

-- 反序列化函数（ASCII字符串 → 表）
function zip.deserialize(s)
    local data = base64_decode(s)
    local index = 1
    local result = {}

    -- 辅助函数：读取变长编码数值
    local function read_value()
        local value, new_index = decode_number(data, index)
        index = new_index
        return math.tointeger(value)
    end

    -- 辅助函数：读取数组
    local function read_array()
        local len = read_value()
        if len < 0 then len = 0 end
        local arr = {}
        for i = 1, len do
            table.insert(arr, read_value())
        end
        return arr
    end

    -- 辅助函数：读取键值对
    local function read_pair()
        return { read_value(), read_value() }
    end

    -- 根据schema重建数据结构
    for section, fields in pairs(SCHEMA) do
        result[section] = {}

        for _, field in ipairs(fields) do
            if field.type == "int" then
                result[section][field.name] = read_value()
            elseif field.type == "int_array" then
                result[section][field.name] = read_array()
            elseif field.type == "int_pair" then
                result[section][field.name] = read_pair()
            end
        end
    end

    return result
end

-- 将字符串分割为64字符块
function zip.split_into_chunks(str, chunk_size)
    chunk_size = chunk_size or 64
    local chunks = {}

    for i = 1, #str, chunk_size do
        table.insert(chunks, str:sub(i, i + chunk_size - 1))
    end

    return chunks
end

return zip
